﻿using Engine.Graphics;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.IO;

namespace Engine.AddinManager
{
    public class AddinManager
    {
        #region Private Fields

        private CompositionContainer _container;

        private Dictionary<string, IAddin> gameDlls;

        [ImportMany(typeof(IAddin))]
        private List<IAddin> GameDlls;

        #endregion Private Fields

        #region Public Constructors

        public AddinManager(Engine Engine)
        {
            this.Engine = Engine;
            string gameDllDirectory = Engine.GetStartupPath() + "\\Addins";
            if (!Directory.Exists(gameDllDirectory))
                Directory.CreateDirectory(gameDllDirectory);

            var catalog = new DirectoryCatalog(gameDllDirectory, "*.GameDll.dll");

            this._container = new CompositionContainer(catalog);

            //Create the CompositionContainer with the parts in the catalog
            this._container = new CompositionContainer(catalog);

            // InitGameDlls();
        }

        #endregion Public Constructors

        #region Public Properties

        public IAddin CurrentAddin
        {
            get;
            private set;
        }

        #endregion Public Properties

        #region Private Properties

        [Export("MainEngine")]
        private Engine Engine { get; set; }

        #endregion Private Properties

        #region Public Methods

        public void SetAddin(string addinName)
        {
            if (this.gameDlls == null)
                InitGameDlls();

            CurrentAddin = GetAddin(addinName);
        }

        #endregion Public Methods

        #region Internal Methods

        internal IAddin GetAddin(string gameDllName)
        {
            IAddin addin;

            if (this.gameDlls == null)
                InitGameDlls();

            if (this.gameDlls.TryGetValue(gameDllName, out addin))
                return addin;

            throw new Exception("Game Dll not found: " + gameDllName);
        }

        internal IShaderArray GetShaderArray(string gameDllName)
        {
            IAddin addin = GetAddin(gameDllName);
            return addin.ShaderArray;
        }

        #endregion Internal Methods

        #region Private Methods

        internal int GetAddinNames()
        {
            throw new NotImplementedException();
        }

        private void InitGameDlls()
        {
            //Fill the imports of this object
            try
            {
                this._container.ComposeParts(this);
                // Add interfaces to dictionary
                this.gameDlls = new Dictionary<string, IAddin>();
                foreach (var item in this.GameDlls)
                {
                    this.gameDlls.Add(item.GetGameName(), item);
                }
            }
            catch (System.Reflection.ReflectionTypeLoadException ex)
            {
                Console.WriteLine(ex.Message);
            }
            catch (CompositionException compositionException)
            {
                Console.WriteLine(compositionException.ToString());
            }
        }

        #endregion Private Methods
    }
}